#include "parse.h"
#include <cassert>
#include "utils/md5.h"

bool Parse::PushRtpPack(PayloadType pt, std::vector<u_char> one_rtp_pack) {
    if (one_rtp_pack.size() <= 13) {
        return false;
    }
    RTP_NALU_HEADER_S rtp_nalu;
    memcpy(&rtp_nalu, &one_rtp_pack[12], 1);
    // printf("rtp_nalu-type:%d\n", rtp_nalu.bit5TYPE);
    if (pt == H264) {
        ParseH264(one_rtp_pack);
    }
    // assert(rtp_nalu.bit5TYPE != 6);
    // assert(rtp_nalu.bit5TYPE > 0 && rtp_nalu.bit5TYPE < 24);

    return true;
}

void Parse::ParseH264(std::vector<u_char> one_rtp_pack) {
    RTP_HEADER_S rtphead;
    UnpackRtpHead(H264, &one_rtp_pack[0], rtphead);

    last_u32SeqNum          = rtphead.u32SeqNum;
    u_int32_t cur_timestamp = rtphead.u32TimeStamp;
    //u_int32_t cur_timestamp = ntohl(rtphead.u32TimeStamp);

    RTP_NALU_HEADER_S rtp_nalu_head;
    memcpy(&rtp_nalu_head, &one_rtp_pack[12], 1);
    // printf("Start-RTP_NALU_HEADER_S-type:%d\n", rtp_nalu_head.bit5TYPE);
    if (rtp_nalu_head.bit5TYPE > 0 && rtp_nalu_head.bit5TYPE < 24) {
        //单一 NAL 单元模式
        // NAL单元的第一字节和RTP荷载头第一个字节重合
        one_pack_h264_.resize(one_rtp_pack.size() - 12);
        memcpy(&one_pack_h264_[0], &one_rtp_pack[12], one_pack_h264_.size());
        switch (rtp_nalu_head.bit5TYPE) {
            case H264_SEI: {
                std::vector<u_char> head{0x00, 0x00, 0x00, 0x01};
                one_pack_h264_.insert(one_pack_h264_.begin(), head.begin(), head.end());
                break;
            }
            case H264_SPS: {
                std::vector<u_char> head{0x00, 0x00, 0x00, 0x01};
                one_pack_h264_.insert(one_pack_h264_.begin(), head.begin(), head.end());
                b_start_ = true;
                break;
            }
            case H264_PPS: {
                std::vector<u_char> head{0x00, 0x00, 0x00, 0x01};
                one_pack_h264_.insert(one_pack_h264_.begin(), head.begin(), head.end());
                break;
            }
            case AUD: {
                //声音，暂时不处理
                break;
            }
            case IDR: {
                // I帧
                std::vector<u_char> head{0x00, 0x00, 0x00, 0x01};
                one_pack_h264_.insert(one_pack_h264_.begin(), head.begin(), head.end());
                count++;
                break;
            }
            case SLICE: {
                // P帧
                std::vector<u_char> head{0x00, 0x00, 0x00, 0x01};
                one_pack_h264_.insert(one_pack_h264_.begin(), head.begin(), head.end());
                count++;
                break;
            }
            default:
                printf("one-RTP_NALU_HEADER_S-type:%d\n", rtp_nalu_head.bit5TYPE);
                assert(0);
                break;
        }
        //回调帧数据
        if (parse_func_ && b_start_) {
            parse_func_(H264, cur_timestamp, one_pack_h264_[4] & 0x1f, one_pack_h264_);
        }
        one_pack_h264_.clear();
        // char type=one_rtp_pack[13];
        // printf("nalu-type:0x%x\n", type);
        // printf("RTP_NALU_HEADER_S-type:%d\n", rtp_nalu_head.bit5TYPE);
    } else {
        //处理组合包
        switch (rtp_nalu_head.bit5TYPE) {
            case FU_A: {
                /**FU-A分片包，解码顺序和传输顺序相同**/
                RTP_FU_HEADER_S rtp_fu_head;
                memcpy(&rtp_fu_head, &one_rtp_pack[13], 1);
                u_char F{0};
                u_char NRI{0};
                u_char TYPE{0};
                // printf("Bit1S:%d\n", rtp_fu_head.Bit1S);
                // printf("Bit1R:%d\n", rtp_fu_head.Bit1R);
                // printf("Bit1E:%d\n", rtp_fu_head.Bit1E);

                if (rtp_fu_head.Bit1S) {
                    //分片开始

                    //开始存储分片数据
                    std::vector<u_char> fu_pack;
                    fu_pack.resize(one_rtp_pack.size() - 14);
                    memcpy(&fu_pack[0], &one_rtp_pack[14], fu_pack.size());
                    one_pack_h264_.insert(one_pack_h264_.end(), fu_pack.begin(), fu_pack.end());
                    // printf("Bit5TYPE:%d\n", rtp_fu_head.Bit5TYPE);
                    // printf("Bit1S-nalu-type:%d\n", one_rtp_pack[13] & 0x1f);
                    u_char              fu_indicator  = one_rtp_pack[12];
                    u_char              fu_header     = one_rtp_pack[13];
                    u_char              nal_unit_type = (fu_indicator & 0xe0) | (fu_header & 0x1f);
                    std::vector<u_char> head{0x00, 0x00, 0x00, 0x01, nal_unit_type};
                    one_pack_h264_.insert(one_pack_h264_.begin(), head.begin(), head.end());
                    // printf("line:%d\n",__LINE__);
                } else if (rtp_fu_head.Bit1E) {
                    if (one_pack_h264_.size() != 0) {
                        std::vector<u_char> fu_pack;
                        fu_pack.resize(one_rtp_pack.size() - 14);
                        memcpy(&fu_pack[0], &one_rtp_pack[14], fu_pack.size());
                        one_pack_h264_.insert(one_pack_h264_.end(), fu_pack.begin(), fu_pack.end());
                        // printf("%d %d %d %d\n", one_pack_h264_[0], one_pack_h264_[1],
                        // one_pack_h264_[2],
                        //        one_pack_h264_[3]);
                        // printf("Bit1E-size:%d nalu-type:%d\n", one_pack_h264_.size(),
                        // one_pack_h264_[4] & 0x1f);
                        if ((one_pack_h264_[4] & 0x1f) == 5) {
                            printf("q-count:%d\n", count);
                            // assert(count==49 || count==0);
                            std::vector<unsigned char> idr_vdata;
                            idr_vdata.assign(one_pack_h264_.begin(), one_pack_h264_.end());
                            int  idrlen = idr_vdata.size();
                            CMD5 m_md5;
                            m_md5.GenerateMD5(&idr_vdata[0], idr_vdata.size());
                            printf("packet.data-idr size:%d md5:%s\n", idr_vdata.size(),
                                   m_md5.ToString().c_str());
                            printf("0x%x 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x\n",
                                   idr_vdata[0], idr_vdata[1], idr_vdata[2], idr_vdata[3],
                                   idr_vdata[4], idr_vdata[5], idr_vdata[6], idr_vdata[7],
                                   idr_vdata[8], idr_vdata[9]);
                            printf(
                              "0x%x 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x\n", idr_vdata[0],
                              idr_vdata[idrlen - 1], idr_vdata[idrlen - 2], idr_vdata[idrlen - 3],
                              idr_vdata[idrlen - 4], idr_vdata[idrlen - 5], idr_vdata[idrlen - 6],
                              idr_vdata[idrlen - 7], idr_vdata[idrlen - 8], idr_vdata[idrlen - 9]);
                            count = 0;
                        } else {
                            count++;
                            // printf("count:%d\n", count);
                        }

                        if (parse_func_ && b_start_) {
                            parse_func_(H264, cur_timestamp, one_pack_h264_[4] & 0x1f,
                                        one_pack_h264_);
                        }

                        one_pack_h264_.clear();
                    }
                    // assert(0);
                } else {
                    //非开始和结束
                    // printf("Bit1S:%d\n", rtp_fu_head.Bit1S);
                    // printf("Bit1R:%d\n", rtp_fu_head.Bit1R);
                    // printf("Bit1E:%d\n", rtp_fu_head.Bit1E);

                    if (one_pack_h264_.size() > 0) {
                        std::vector<u_char> fu_pack;
                        fu_pack.resize(one_rtp_pack.size() - 14);
                        memcpy(&fu_pack[0], &one_rtp_pack[14], fu_pack.size());
                        one_pack_h264_.insert(one_pack_h264_.end(), fu_pack.begin(), fu_pack.end());
                    }
                }

            } break;
            default:
                printf("many-RTP_NALU_HEADER_S-type:%d\n", rtp_nalu_head.bit5TYPE);
                assert(0);
                break;
        }
    }
}

uint32_t last_num{0};
bool     Parse::UnpackRtpHead(PayloadType pt, u_char* rtp_head, RTP_HEADER_S& rtphead) {
    mempcpy(&rtphead, rtp_head, 2);
    /**RTP 序列号**/
    rtphead.u32SeqNum = 0;
    rtphead.u32SeqNum = (rtp_head[2] & 0xff);
    rtphead.u32SeqNum <<= 8;
    rtphead.u32SeqNum |= (rtp_head[3] & 0xff);
    /**RTP 时间戳**/
    rtphead.u32TimeStamp = (rtp_head[4] & 0xff);
    rtphead.u32TimeStamp <<= 8;
    rtphead.u32TimeStamp |= (rtp_head[5] & 0xff);
    rtphead.u32TimeStamp <<= 8;
    rtphead.u32TimeStamp |= (rtp_head[6] & 0xff);
    rtphead.u32TimeStamp <<= 8;
    rtphead.u32TimeStamp |= (rtp_head[7] & 0xff);

    if (rtphead.bit1Version == 2 && rtphead.bit7PayLoadType == pt) {
        // assert(rtphead.bit1Marker == 0);
        // printf("Version:%d\n", rtphead.bit1Version);
        // printf("bit1Padding:%d\n", rtphead.bit1Padding);
        // printf("bit1Extension:%d\n", rtphead.bit1Extension);
        // printf("bit4CsrcLen:%d\n", rtphead.bit4CsrcLen);
        // printf("bit1Marker:%d\n", rtphead.bit1Marker);
        // printf("PayLoadType:%d\n", rtphead.bit7PayLoadType);
        // printf("parse-SeqNum:%d\n", rtphead.u32SeqNum);
        // printf("TimeStamp:%u\n", rtphead.u32TimeStamp);
        if (last_num != 0) {
            // printf("dh:%d\n", rtphead.u32SeqNum - last_num);
            // printf("u32SeqNum:%u last_num:%d\n", rtphead.u32SeqNum, last_num);
            assert(rtphead.u32SeqNum - last_num == 1);
        }
        return true;
    }

    return false;
}